package seismosurfer.database;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import seismosurfer.data.CatalogData;
import seismosurfer.util.SeismoException;
import seismosurfer.util.TimeUtil;

/**
 * A DAO class that encapsulates all access to the
 * CATALOG table.
 *
 */
public class CatalogDAO extends DAOObject {
    
    /** Query to find all rows from the CATALOG table */
    protected static final String CATALOG_TABLE = " SELECT * FROM catalog ";

    private static final String UPDATE_URL = " UPDATE catalog "
            + " SET url = ? " + " WHERE catid = ? ";

    private List catalogs = new ArrayList(4);
    
    /**
     * Catalog is a small table so all entries are loaded into memory,
     * during instantiation.
     *
     */
    public CatalogDAO() {

        loadCatalogs();

    }
    
    /**
     * Updates the url of a catalog.
     * 
     * @param catID The catalog id.
     * @param url The string that holds the new url.
     */
    public void updateURL(int catID, String url) {
        PreparedStatement ps = null;
        try {
            ps = DB.prepare(UPDATE_URL);
            ps.setInt(1, catID);
            ps.setString(2, url);

            ps.executeUpdate();
        } catch (SQLException e) {
            throw new SeismoException(e);
        } finally {
            DB.cleanUp(ps);
        }
    }
    
    /**
     * Retrieves a list with all the catalogs data.
     * 
     * @return A list with all the catalogs data.
     */
    public List getCatalogs() {
        return catalogs;
    }
    
    /**
     * Loads a row from the database into a CatalogData object.
     * 
     * @param rs The resultset from which the row will be loaded.
     * @return A CatalogData object which contains the data of a row.
     * @throws SQLException
     */
    public static CatalogData load(ResultSet rs) throws SQLException {
        CatalogData catData = new CatalogData();

        catData.setCatalogID(rs.getInt(1));
        catData.setCatalogName(rs.getString(2));
        catData.setCatalogSource(rs.getString(3));
        catData.setCatalogURL(rs.getString(4));
        catData.setCatalogPriority(rs.getInt(5));
        catData.setCatalogInfo(rs.getString(6));
        catData.setUpdatable(toBoolean(rs.getInt(7)));
        catData.setPeriod(TimeUtil.toMillis(rs.getInt(8)));
        catData.setDelay(TimeUtil.toMillis(rs.getInt(9)));

        return catData;
    }
    
    /**
     * Retrieves all the data sources from the database.
     * 
     * @return A set of data sources.
     */
    public Set getSources() {

        Set sources = new HashSet();

        for (Iterator iter = catalogs.iterator(); iter.hasNext();) {
            CatalogData item = (CatalogData) iter.next();
            sources.add(item.getCatalogSource());
        }

        return sources;
    }
    
    /**
     * Loads all catalog data from the database into memory.
     *
     */
    protected void loadCatalogs() {

        PreparedStatement stmt = null;
        ResultSet rs = null;

        try {

            catalogs.clear();

            stmt = DB.prepare(CATALOG_TABLE);

            rs = stmt.executeQuery();

            while (rs.next()) {
                this.catalogs.add(load(rs));
            }

            System.out.println("Catalogs Count :" + catalogs.size());

        } catch (SQLException e) {
            throw new SeismoException(e);
        } finally {
            DB.cleanUp(stmt, rs);
        }

    }
    
    /**
     * Gets a catalog`s priority, which is used when dealing with 
     * duplicate records.
     *  
     * @param catalogID The catalog`s id.
     * @return The priority of the catalog.
     */
    public int getCatalogPriority(int catalogID) {

        int priority = -1;

        for (int i = 0; i < catalogs.size(); i++) {

            CatalogData catData = (CatalogData) catalogs.get(i);

            if (catData.getCatalogID() == catalogID) {
                priority = catData.getCatalogPriority();
                break;
            }

        }
        return priority;
    }
    
    /**
     * Retrieves the catalog`s data given its id.
     * 
     * @param id The catalog`s id.
     * @return The DTO object with the catalog`s data.
     */
    public CatalogData getCatalog(int id) {

        for (int i = 0; i < this.catalogs.size(); i++) {
            CatalogData catData = (CatalogData) catalogs.get(i);
            if (catData.getCatalogID() == id) {
                return catData;
            }
        }
        return null;
    }
    
    /**
     * Gets the catalog`s name given its id.
     * 
     * @param catalogID The catalog`s id.
     * @return The catalog name.
     */
    public String getCatalogName(int catalogID) {

        String catName = "";

        for (int i = 0; i < this.catalogs.size(); i++) {

            CatalogData catData = (CatalogData) catalogs.get(i);

            if (catData.getCatalogID() == catalogID) {
                catName = catData.getCatalogName();
                break;
            }

        }
        return catName;

    }
    
    /**
     * Gets a catalog`s (data) source name given its id.
     * 
     * @param catalogID the catalog`s id
     * @return The catalog`s source name
     */
    public String getCatalogSource(int catalogID) {

        String catSource = "";

        for (int i = 0; i < catalogs.size(); i++) {

            CatalogData catData = (CatalogData) catalogs.get(i);

            if (catData.getCatalogID() == catalogID) {
                catSource = catData.getCatalogSource();
                break;
            }

        }
        return catSource;

    }
    
    /**
     * Gets the number of catalogs.
     * 
     * @return the number of catalogs
     */
    public int getCatalogCount() {
        return catalogs.size();
    }
    
    /**
     * Gets the catalog`s data given its name.
     * 
     * @param catalogName the name of the catalog
     * @return a CatalogData object
     */
    public CatalogData getCatalogData(String catalogName) {

        CatalogData catData = new CatalogData();

        for (int i = 0; i < catalogs.size(); i++) {

            catData = (CatalogData) catalogs.get(i);

            if (catData.getCatalogName().equalsIgnoreCase(catalogName)) {
                return catData;
            }

        }

        return catData;

    }

}
